/*	Copyright 2007 - Xavier Baro (xbaro@cvc.uab.cat)

	This file is part of eapmlib.

    Eapmlib is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or any 
	later version.

    Eapmlib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
/*! \file Chromosome.cpp
\brief Chromosome class source
\author Xavier Bar Sol

This file contains the declaration of the chromosome class. This class containt all the
information of an instance of a certain model. The data can be stored using different
representations.
*/
#include "Chromosome.h"
#include <math.h>

Evolutive::CChromosome::CChromosome(void): m_Length(0), m_BitString(NULL),m_NumFields(0),m_FieldsDesc(NULL),m_CodingMethod(CODE_GRAY),m_BinBitString(NULL),m_GrayBitString(NULL),m_IntBitString(NULL),m_DblBitString(NULL)
{	
}

Evolutive::CChromosome::CChromosome(const CChromosome &C) : m_Length(0), m_BitString(NULL),m_NumFields(0),m_FieldsDesc(NULL),m_CodingMethod(CODE_GRAY),m_BinBitString(NULL),m_GrayBitString(NULL),m_IntBitString(NULL),m_DblBitString(NULL)
{
	Clone(C);
}

Evolutive::CChromosome::~CChromosome(void)
{
	// Free allocated memory
	if(m_BinBitString)
		delete[] m_BinBitString;
	if(m_GrayBitString)
		delete[] m_GrayBitString;
	if(m_IntBitString)
		delete[] m_IntBitString;
	if(m_DblBitString)
		delete[] m_DblBitString;
	if(m_FieldsDesc)
		delete[] m_FieldsDesc;
}

void Evolutive::CChromosome::Clone(const Evolutive::CChromosome &C)
{
	/*// Free old memory
	if(m_BinBitString)
		delete[] m_BinBitString;
	if(m_GrayBitString)
		delete[] m_GrayBitString;
	if(m_IntBitString)
		delete[] m_IntBitString;
	if(m_DblBitString)
		delete[] m_DblBitString;
	if(m_FieldsDesc)
		delete[] m_FieldsDesc;*/
	
	// Copy the valued parameters
	m_Length=C.m_Length;	
	m_NumFields=C.m_NumFields;
	m_CodingMethod=C.m_CodingMethod;
		
	// Allocate the new memory	
	m_BinBitString=new unsigned char[m_Length];
	m_GrayBitString=new unsigned char[m_Length];
	m_IntBitString=new unsigned int[m_NumFields];
	m_DblBitString=new double[m_NumFields];
	m_FieldsDesc=new int[m_NumFields];

	// Set all the representations to 0
	memcpy(m_BinBitString,C.m_BinBitString,sizeof(unsigned char)*m_Length);
	memcpy(m_GrayBitString,C.m_GrayBitString,sizeof(unsigned char)*m_Length);
	memcpy(m_IntBitString,C.m_IntBitString,sizeof(unsigned int)*m_NumFields);
	memcpy(m_DblBitString,C.m_DblBitString,sizeof(double)*m_NumFields);
	memcpy(m_FieldsDesc,C.m_FieldsDesc,sizeof(int)*m_NumFields);
		
	// Sets the default bit string pointer to the correct bitstring
	switch(m_CodingMethod)
	{	
	case CODE_GRAY:
		m_BitString=m_GrayBitString;
		break;
	case CODE_BINARY:
		m_BitString=m_BinBitString;
		break;
	case CODE_DECIMAL_INT:
		m_BitString=NULL;	
		break;
	case CODE_DECIMAL_DBL:
		m_BitString=NULL;	
		break;
	}
}

void Evolutive::CChromosome::SetFields(int NumFields,int *NumBits)
{
	register int i;

	// Remove the previous definition
	if(m_FieldsDesc)
		delete[] m_FieldsDesc;

	// Create the new description vector
	m_NumFields=NumFields;
	m_FieldsDesc=new int[m_NumFields];

	// Assign the values and count the total number of bits
	m_Length=0;
	for(i=0;i<m_NumFields;i++)
	{
		m_FieldsDesc[i]=NumBits[i];
		m_Length+=NumBits[i];
	}

	// Remove the old representations
	if(m_BinBitString)
		delete[] m_BinBitString;
	if(m_GrayBitString)
		delete[] m_GrayBitString;
	if(m_IntBitString)
		delete[] m_IntBitString;
	if(m_DblBitString)
		delete[] m_DblBitString;

	// Create the new representations
	m_BinBitString=new unsigned char[m_Length];
	m_GrayBitString=new unsigned char[m_Length];
	m_IntBitString=new unsigned int[m_NumFields];
	m_DblBitString=new double[m_NumFields];

	// Set all the representations to 0
	memset(m_BinBitString,0,sizeof(unsigned char)*m_Length);
	memset(m_GrayBitString,0,sizeof(unsigned char)*m_Length);
	memset(m_IntBitString,0,sizeof(unsigned int)*m_NumFields);
	memset(m_DblBitString,0,sizeof(double)*m_NumFields);

	// Sets the default bit string pointer to the correct bitstring
	switch(m_CodingMethod)
	{	
	case CODE_GRAY:
		m_BitString=m_GrayBitString;
		break;
	case CODE_BINARY:
		m_BitString=m_BinBitString;
		break;
	case CODE_DECIMAL_INT:
		m_BitString=NULL;
		break;
	case CODE_DECIMAL_DBL:
		m_BitString=NULL;
		break;
	}
}

void Evolutive::CChromosome::SetCode(CODING_METHOD Method)
{
	// Store the new value
	m_CodingMethod=Method;

	// Set the default bit string pointer to the correct bitstring
	switch(m_CodingMethod)
	{	
	case CODE_GRAY:
		m_BitString=m_GrayBitString;
		break;
	case CODE_BINARY:
		m_BitString=m_BinBitString;
		break;
	case CODE_DECIMAL_INT:
		m_BitString=NULL;
		break;
	case CODE_DECIMAL_DBL:
		m_BitString=NULL;
		break;
	}
}

void Evolutive::CChromosome::Decode()
{
	register int i;
	unsigned char *pBBitString=NULL,*pGBitString=NULL;

	switch(m_CodingMethod)
	{	
	case CODE_GRAY:
		// Convert the gray code to binary code
		pBBitString=m_BinBitString;
		pGBitString=m_GrayBitString;
		for(i=0;i<m_NumFields;i++)
		{
			Grayc2Bin(pGBitString,pBBitString,m_FieldsDesc[i]);
			pBBitString+=m_FieldsDesc[i];
			pGBitString+=m_FieldsDesc[i];
		}		
	case CODE_BINARY:
		// Convert the binary code to decimal
		pBBitString=m_BinBitString;
		for(i=0;i<m_NumFields;i++)
		{
			// Convert the field from binary to integer
			m_IntBitString[i]=Bin2Dec(pBBitString,m_FieldsDesc[i]);
			pBBitString+=m_FieldsDesc[i];

			// Copy this integer to the double representation
			m_DblBitString[i]=static_cast<double>(m_IntBitString[i]);
		}
		break;
	case CODE_DECIMAL_INT:
		// Copy the values to the double valued array
		for(i=0;i<m_NumFields;i++)
		{				
			m_DblBitString[i]=static_cast<double>(m_IntBitString[i]);
		}
		break;
	case CODE_DECIMAL_DBL:
		// No action is required
		break;
	}	
}
 
const string Evolutive::CChromosome::ToString(void)
{
	string OutStr;

	// Shows all the available representations for the chromosome
	if(m_Length)
	{
		OutStr="";		
		switch(m_CodingMethod)
		{	
		case CODE_GRAY:
			OutStr+="G: ";
			OutStr+=ToString(m_GrayBitString);
			OutStr+="\n";
		case CODE_BINARY:
			OutStr+="B: ";
			OutStr+=ToString(m_BinBitString);
			OutStr+="\n";
		case CODE_DECIMAL_INT:
			OutStr+="D: ";
			OutStr+=ToString(m_IntBitString);
		case CODE_DECIMAL_DBL:
			OutStr+="F: ";
			OutStr+=ToString(m_DblBitString);
		}
	}
	else
	{
		OutStr="<Empty>";
	}

	return OutStr;
}

const string Evolutive::CChromosome::ToString(unsigned char *BitString)		
{
	string OutStr;	
	char Buffer[4];
	register int i,j;
	unsigned char *pAct=NULL,*pBaseField=NULL;

	if(!m_Length)
	{
		OutStr="<Empty>";
	}
	else
	{
		pBaseField=BitString;
		OutStr="<";
		for(j=0;j<m_NumFields;j++)
		{
			if(j>0)
				OutStr+=" | ";
			pAct=&(pBaseField[m_FieldsDesc[j]-1]);
			for(i=0;i<m_FieldsDesc[j];i++)
			{				
				OutStr+=" ";				
				//_itoa_s(*pAct,Buffer,4,10);
				sprintf(Buffer,"%d",*pAct);
				OutStr+=Buffer;
				pAct--;				
				pBaseField++;
			}			
			
		}
		OutStr+=" >";
	}

	return OutStr;
}

const string Evolutive::CChromosome::ToString(unsigned int *DecBitString)
{
	string OutStr;	
	char Buffer[4];
	register int i;
	
	if(!m_Length)
	{
		OutStr="<Empty>";
	}
	else
	{		
		OutStr="<";
		for(i=0;i<m_NumFields;i++)
		{			
			if(i>0)
				OutStr+=" | ";
			OutStr+=" ";			
			//_itoa_s(DecBitString[i],Buffer,4,10);
			sprintf(Buffer,"%d",DecBitString[i]);
			OutStr+=Buffer;
		}
		OutStr+=" >";
	}

	return OutStr;
}

const string Evolutive::CChromosome::ToString(double *DblBitString)
{
	string OutStr;	
	char Buffer[4];
	register int i;

	if(!m_Length)
	{
		OutStr="<Empty>";
	}
	else
	{		
		OutStr="<";
		for(i=0;i<m_NumFields;i++)
		{			
			if(i>0)
				OutStr+=" | ";
			OutStr+=" ";						
			sprintf(Buffer,"%e",DblBitString[i]);
			OutStr+=Buffer;
		}
		OutStr+=" >";
	}

	return OutStr;
}

void Evolutive::CChromosome::Dec2Bin(unsigned int Number,unsigned char *BitString,int NumBits)
{
	unsigned int Remain;
	unsigned char *pBitString=NULL;
	register int i;

	// Point to the last position
	pBitString=BitString;

	// Build the binary representation
	for(i=0;i<NumBits;i++)
	{
		if(Number>0)
		{
			// Take the module
			Remain=Number % 2;

			// Whittle down the decimal number
			Number/=2;

			// Converts digit 0 or 1 to character '0' or '1'
			*pBitString = (unsigned char)Remain;
		}
		else
		{
			*pBitString = 0;
		}

		// Move the pointer
		pBitString++;
	}
}
			 
void Evolutive::CChromosome::Bin2Grayc(unsigned char *BitString,unsigned char *GrayString,int NumBits)
{
	unsigned char *pBitString=NULL;
	unsigned char *pGrayString=NULL;
		
	// The most significant bit is equal
	GrayString[NumBits-1]=BitString[NumBits-1];

	// The next of the bits can be obtained by xor operations
	pGrayString=&(GrayString[NumBits-2]);
	pBitString=&(BitString[NumBits-2]);
	while(pGrayString>=GrayString)
	{
		*pGrayString=pBitString[0]^pBitString[1];
		pGrayString--;
		pBitString--;
	}
}

unsigned int Evolutive::CChromosome::Bin2Dec(unsigned char *BitString,int NumBits)
{
	unsigned int PowVal;
	unsigned int RetVal;
	unsigned char *pBitString=NULL;
	register int i;

	PowVal=1;
	RetVal=0;
	
	// Point to the last position
	pBitString=BitString;

	// Build the binary representation
	for(i=0;i<NumBits;i++)
	{
		if(*pBitString)
		{
			RetVal+=PowVal;
		}
		PowVal*=2;

		pBitString++;
	}
	
	return RetVal;
}

// Convert a gray coded string to a binary string
void Evolutive::CChromosome::Grayc2Bin(unsigned char *GrayString,unsigned char *BitString,int NumBits)
{
	unsigned char *pBitString=NULL;
	unsigned char *pGrayString=NULL;
		
	// The most significant bit is equal
	BitString[NumBits-1]=GrayString[NumBits-1];

	// The next of the bits can be obtained by xor operations
	pGrayString=&(GrayString[NumBits-2]);
	pBitString=&(BitString[NumBits-2]);
	while(pBitString>=BitString)
	{
		*pBitString=pBitString[1]^pGrayString[0];
		pGrayString--;
		pBitString--;
	}
}

void Evolutive::CChromosome::Generate(double *ProbDist)
{
	register int i;
	double val;

	switch(m_CodingMethod)
	{	
	case CODE_GRAY:	
	case CODE_BINARY:
		// Binary representation
		for(i=0;i<m_Length;i++)
		{
			val=RAND_VALUE();
			if(val<=ProbDist[i])
				m_BitString[i]=1;
			else
				m_BitString[i]=0;
		}		
		break;
	case CODE_DECIMAL_INT:
		// Integer Decimal representation
		for(i=0;i<m_NumFields;i++)
		{
			val=RAND_VALUE();			
			if(val<=ProbDist[i])
				m_IntBitString[i]=1;
			else
				m_IntBitString[i]=0;
		}
		break;
	case CODE_DECIMAL_DBL:
		// Double Decimal representation
		for(i=0;i<m_NumFields;i++)
		{
			val=RAND_VALUE();			
			if(val<=ProbDist[i])
				m_DblBitString[i]=1;
			else
				m_DblBitString[i]=0;
		}
		break;
	}	
	Decode();
}

void Evolutive::CChromosome::Generate(void)
{
	register int i;
	double val;
	CODING_METHOD OriginalCoding=m_CodingMethod;

	if(m_CodingMethod==CODE_DECIMAL_INT || m_CodingMethod==CODE_DECIMAL_DBL)
	{
		// Decimal representation

		// Generate a binary string		
		for(i=0;i<m_Length;i++)
		{
			val=RAND_VALUE();
			if(val>0.5)
				m_GrayBitString[i]=1;
			else
				m_GrayBitString[i]=0;
		}

		// Change the representation 
		m_CodingMethod=CODE_GRAY;

		// Codify the chromosome
		Decode();
		
		// Set the correct representation again
		m_CodingMethod=OriginalCoding;
	}
	else
	{
		// Binary representation
		for(i=0;i<m_Length;i++)
		{
			val=RAND_VALUE();
			if(val>0.5)
				m_BitString[i]=1;
			else
				m_BitString[i]=0;
		}

		// Decode the chromosome to obtain the decimal representation
		Decode();
	}

}

unsigned char *Evolutive::CChromosome::GetBitStringPtr(void)
{
	return m_BitString;
}

unsigned int *Evolutive::CChromosome::GetIntStringPtr(void)
{
	return m_IntBitString;
}

double *Evolutive::CChromosome::GetDblStringPtr(void)
{
	return m_DblBitString;
}

void Evolutive::CChromosome::UniformMutation(double Prob)
{
	register int i;
	double val;

	for(i=0;i<m_Length;i++)
	{
		val=RAND_VALUE();		
		if(val<=Prob)
			m_BitString[i]=1-m_BitString[i];
	}
	Decode();
}

int Evolutive::CChromosome::GetNumBits(void)
{
	return m_Length;
}

std::ostream& operator<<(std::ostream &stream, Evolutive::CChromosome C)
{
  stream << C.ToString() << endl;

  return stream;
}

Evolutive::CChromosome& Evolutive::CChromosome::operator=( const Evolutive::CChromosome &C )
{
	if ( this != &C )
	{
		if(m_BinBitString)
			delete[] m_BinBitString;
		if(m_GrayBitString)
			delete[] m_GrayBitString;
		if(m_IntBitString)
			delete[] m_IntBitString;
		if(m_DblBitString)
			delete[] m_DblBitString;
		if(m_FieldsDesc)
			delete[] m_FieldsDesc;
		Clone(C);
	}
	return *this;
}

bool Evolutive::CChromosome::operator==(Evolutive::CChromosome C)
{
	register int i;
	unsigned char *pC=NULL;
	unsigned int *pInt=NULL;
	double *pDbl=NULL;

	// Check the codification for both Chromosomes
	if(m_CodingMethod!=C.GetCodingMethod())
	{
		// TODO: Convert both chromosomes to a common representation before compare them.
		return false;
	}
	
	if(m_CodingMethod==CODE_DECIMAL_INT || m_CodingMethod==CODE_DECIMAL_DBL)
	{
		// Decimal representation

		// If the number of variables is different consider both chromosomes different
		if(m_NumFields!=C.GetNumFields())
			return false;

		// Point to the decimal string
		switch(m_CodingMethod)
		{
		case CODE_DECIMAL_INT:
			// Point to the values
			pInt=C.GetIntStringPtr();
			
			// Compare the values
			for(i=0;i<m_NumFields;i++)
			{
				if(pInt[i]!=m_IntBitString[i])
					return false;
			}
			break;
		case CODE_DECIMAL_DBL:
			// Point to the values
			pDbl=C.GetDblStringPtr();

			// Compare the values
			for(i=0;i<m_NumFields;i++)
			{
				if(pDbl[i]!=m_DblBitString[i])
					return false;
			}
			break;
		}
	}
	else
	{
		// Binary representation
	
		// If the number of bits is different consider both chromosomes different
		if(m_Length!=C.GetNumBits())
			return false;

		// Point to the bit string	
		pC=C.GetBitStringPtr();

		// Compare the bitstrings
		for(i=0;i<m_Length;i++)
		{
			if(pC[i]!=m_BitString[i])
				return false;
		}
	}

	return true;
}

bool Evolutive::CChromosome::operator!=(Evolutive::CChromosome C)
{
	return !(*this==C);
}

int Evolutive::CChromosome::GetNumFields(void)
{
	return m_NumFields;
}

void Evolutive::CChromosome::Code()
{
	register int i;
	unsigned char *pBBitString=NULL,*pGBitString=NULL;

	// Point to the binary representations
	pBBitString=m_BinBitString;
	pGBitString=m_GrayBitString;

	// Codify each field
	for(i=0;i<m_NumFields;i++)
	{		
		// Convert to binary code
		switch(m_CodingMethod)
		{
		case CODE_DECIMAL_INT:
			// Convert this integer field to the binary representation
			Dec2Bin(m_IntBitString[i],pBBitString,m_FieldsDesc[i]);
			break;
		case CODE_DECIMAL_DBL:
			// Convert this double field to the binary representation
			Dec2Bin(m_DblBitString[i],pBBitString,m_FieldsDesc[i]);
			break;
		}		
	
		// Convert to gray code
		Bin2Grayc(pBBitString,pGBitString,m_FieldsDesc[i]);

		// Move to next field
		pBBitString+=m_FieldsDesc[i];
		pGBitString+=m_FieldsDesc[i];
	}
}

void Evolutive::CChromosome::SetDecValue(unsigned int Data[])
{
	// Assign the correct codification
	m_CodingMethod=CODE_DECIMAL_INT;

	// Copy the new values
	memcpy(m_IntBitString,Data,m_NumFields*sizeof(unsigned int));

	// Codify the data
	Code();
}

void Evolutive::CChromosome::SetDecValue(double Data[])
{
	// Assign the correct codification
	m_CodingMethod=CODE_DECIMAL_DBL;

	// Copy the new values
	memcpy(m_DblBitString,Data,m_NumFields*sizeof(double));

	// Codify the data
	Code();
}

Evolutive::CODING_METHOD Evolutive::CChromosome::GetCodingMethod(void)
{
	return m_CodingMethod;
}

Evolutive::CChromosome* Evolutive::operator<<(Evolutive::CChromosome* in, NBE::VarSet& x)
{
    register int i;	
	unsigned int *pIntData=NULL;
	double *pDblData=NULL;
	unsigned char *pBitData=NULL;

	// Obtain the number of values to be copied
	switch(in->GetCodingMethod())		
	{
	case CODE_DECIMAL_INT:
		// Point to the data
		pIntData=in->GetIntStringPtr();

		// Copy each value to the integer array
		for(i=0;i<x.getNumVars();i++)
		{			
			//! Copy to the decimal value
			pIntData[i]=(unsigned int)x[i];
		}   

		// Code the data to obtain the binary representation
		in->Code();
		break;
	case CODE_DECIMAL_DBL:
		// Point to the data
		pDblData=in->GetDblStringPtr();

		// Copy each value to the integer array
		for(i=0;i<x.getNumVars();i++)
		{			
			//! Copy to the decimal value
			pDblData[i]=(double)x[i];
		}   

		// Code the data to obtain the binary representation
		in->Code();
		break;
	default:
		// Point to the data
		pBitData=in->GetBitStringPtr();

		// Copy each num to the bit array
		for(i=0;i<x.getNumVars();i++)
		{			
			// Copy to the bit
			pBitData[i]=(unsigned char)x[i];
		}   

		// Decode the chromosome to obtain the decimal representation
		in->Decode();
	}
	
    return in;
}

Evolutive::CChromosome& Evolutive::operator>>(Evolutive::CChromosome& in, NBE::VarSet& x)
{
    register int i;
	double v;
	GrowArray<double> Values;
	int NumValues;
	unsigned int *pIntData=NULL;
	double *pDblData=NULL;
	unsigned char *pBitData=NULL;

	// Obtain the number of values to be copied
	switch(in.GetCodingMethod())
	{
	case CODE_DECIMAL_INT:	
		// Point to the data
		pIntData=in.GetIntStringPtr();
		NumValues=in.GetNumFields();

		// Copy each value to the temporal array
		for(i=0;i<NumValues;i++)
		{
			// Copy to a double variable
			v=static_cast<double>(pIntData[i]);

			// Append to the array of values
			Values.append(v);
		}
		break;
	case CODE_DECIMAL_DBL:	
		// Point to the data
		pDblData=in.GetDblStringPtr();
		NumValues=in.GetNumFields();

		// Copy each value to the temporal array
		for(i=0;i<NumValues;i++)
		{
			// Copy to a double variable
			v=pDblData[i];

			// Append to the array of values
			Values.append(v);
		}
		break;
	default:		
		// Point to the data
		pBitData=in.GetBitStringPtr();
		NumValues=in.GetNumBits();

		// Copy each bit to the temporal array
		for(i=0;i<NumValues;i++)
		{
			// Copy to a double variable
			v=static_cast<double>(pBitData[i]);

			// Append to the array of values
			Values.append(v);
		}
	}   
    
    // Assign to the VarSet object
    x = VarSet(NumSet<double>(Values.getArray(), Values.size()));

    return in;
}

void Evolutive::CChromosome::Dbl2Bin(double Number,unsigned char *BitString,int NumBits)
{
	unsigned long Mask32=1;
	unsigned long *Number32=NULL;
	unsigned long long Mask64=1;
	unsigned long long *Number64=NULL;
	int Count=0;

	// NumBits must be either 32 or 64
	if(NumBits!=32 && NumBits!=64)
		throw CEvolutiveLibException("Incorrect number of bits. Double must have 32/64 bits",__FILE__,__LINE__,"Bin2Dbl");

	// Convert to a bit string
	switch(NumBits)
	{
	case 32:
		Mask32<<=31;
		Number32=reinterpret_cast<unsigned long*>(&Number);
		Count=0;
		while(Mask32>0)
		{
			BitString[Count]=((*Number32 & Mask32)? 1:0);
			Mask32>>=1;
			Count++;
		}
		break;
	case 64:		
		Mask64<<=63;
		Number64=reinterpret_cast<unsigned long long*>(&Number);
		Count=0;
		while(Mask64>0)
		{
			BitString[Count]=((*Number64 & Mask64)? 1:0);
			Mask64>>=1;
			Count++;
		}
		break;
	}
}

double Evolutive::CChromosome::Bin2Dbl(unsigned char *BitString,int NumBits)
{
	int i, bit, j;
	int sign;				//value for sign bit
	int begin = 0;			//beginning of string
	int end = 31;			//end of string
	int exp_pos = 1;		//where exponent field begins
	int mantissa_pos = 9;	//where mantissa field begins
	int exponent = 0;		//value for exponent
	double mantissa = 0;	//value for mantissa
	int ByteOrder=0;
	
	//Checking input string to see whether it is 32 or 64 bits
	//then setting variables accordingly
	if(NumBits == 32)
	{
		if(ByteOrder)
		{
			begin = 31;
			end = 0;
		}
		else 
		{
			begin = 0;
			end = 31;
		}
		j = 7;
		
	}
	else if(NumBits == 64)
	{
		if(ByteOrder)
		{
			begin = 63;
			end = 0;
		}
		else
		{
			begin = 0;
			end = 63;
		}
		exp_pos = 1;
		mantissa_pos = 12;
		j = 10;
	}
	else 
	{
		throw CEvolutiveLibException("Incorrect number of bits. Double must have 64 bits",__FILE__,__LINE__,"Dbl2Bin");
	}
	//end checking input string
	
	//Check sign bit	
	sign=static_cast<int>(BitString[begin]);	
	if(sign) sign = -1;
	else sign = 1;
	
	//For loop for calculating the exponent
	for(i = begin + exp_pos; i < begin + mantissa_pos; j--)
	{
		bit=static_cast<int>(BitString[begin + i]);
		exponent = exponent + pow(2.0,j)*bit;
		
		if(begin) i--;
		else i++;
	}
	if(NumBits == 32) exponent = exponent - 127;
	else exponent = exponent - 1023; 
	
	//For loop for calculating Mantissa
	j = -1;
	for(i = begin + mantissa_pos; i < begin + end; j--)
	{
		bit=bit=static_cast<int>(BitString[begin + i]);		
	
		mantissa = mantissa + pow(2.0,j)*bit;
		
		if(begin) i--;
		else i++;
	}
	mantissa += 1;
	
	return sign*(pow(2.0,exponent))*mantissa;
}